package cn.coderwe.controller;

import cn.coderwe.model.Chapter;
import cn.coderwe.model.MultiLevelBook;
import cn.coderwe.model.Volume;
import cn.coderwe.service.BookReader;
import cn.coderwe.util.PathUtil;
import cn.hutool.core.io.FileUtil;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.text.Text;
import javafx.stage.FileChooser;
import nl.siegmann.epublib.domain.*;
import nl.siegmann.epublib.epub.EpubWriter;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;

/**
 * @author : coderwe
 */
public class EpubDesktopController {
    public Button chooseBtn;
    public ImageView coverImage;
    public Text bookNameText;
    public Text bookWriterText;
    public Text bookIntrosText;
    public TreeView<Object> directoryTree;
    public TextArea contentText;
    public ScrollPane introPane;
    private MultiLevelBook multiLevelBook;

    public void chooseFile(ActionEvent actionEvent) throws IOException {
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("请选择小说");
        fileChooser.getExtensionFilters().addAll(
                new FileChooser.ExtensionFilter("txt", "*.txt")
        );
        fileChooser.setInitialDirectory(new java.io.File("."));
        fileChooser.setInitialFileName("小说.txt");
        File file = fileChooser.showOpenDialog(chooseBtn.getScene().getWindow());
        if (file == null) {
            return;
        }
        String bookName = FileUtil.getPrefix(file.getAbsoluteFile());
        multiLevelBook = new BookReader().read(file.getAbsolutePath());
        List<Volume> volumes = multiLevelBook.getVolumes();
        TreeItem<Object> root = new TreeItem<>();
        if (volumes.size() == 1) {
            Volume volume = volumes.get(0);
            for (Chapter chapter : volume.getChapters()) {
                TreeItem<Object> chapterItem = new TreeItem<>(chapter);
                root.getChildren().add(chapterItem);
            }
        } else {
            for (int i = 0; i < volumes.size(); i++) {
                Volume volume = volumes.get(i);
                TreeItem<Object> volumeItem = new TreeItem<>(volume);
                for (int j = 0; j < volume.getChapters().size(); j++) {
                    Chapter chapter = volume.getChapters().get(j);
                    TreeItem<Object> chapterItem = new TreeItem<>(chapter);
                    volumeItem.getChildren().add(chapterItem);
                }
                root.getChildren().add(volumeItem);
            }
        }
        directoryTree.setRoot(root);
        bookNameText.setText(bookName);
        bookWriterText.setText(multiLevelBook.getBookWriter());
        bookIntrosText.setText(String.join("\n", multiLevelBook.getIntros()));
    }

    public void createEpub(ActionEvent actionEvent) {
        //打开文件选择器并把epub生成在选择器选中的路径下
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("请选择输出路径");
        fileChooser.getExtensionFilters().addAll(
                new FileChooser.ExtensionFilter("epub", "*.epub")
        );
        fileChooser.setInitialDirectory(new java.io.File("."));
        String bookName = multiLevelBook.getBookName();
        fileChooser.setInitialFileName(bookName + ".epub");
        File file = fileChooser.showSaveDialog(chooseBtn.getScene().getWindow());
        if (file == null) {
            return;
        }
        System.out.println(file.getAbsoluteFile());
        System.out.println("生成epub");
        //模板引擎
        TemplateEngine engine = new TemplateEngine();
        //读取磁盘中的模板文件
        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
        resolver.setPrefix("/");
        resolver.setSuffix(".html");
        engine.setTemplateResolver(resolver);
        Context context = new Context();
        try {
            Book book = new Book();
            Metadata metadata = book.getMetadata();
            metadata.addTitle(bookName);
            metadata.addAuthor(new Author(multiLevelBook.getBookWriter()));
            // 出版社
            metadata.setLanguage("zh");
            try (InputStream coverImageIps = Files.newInputStream(Paths.get(PathUtil.getTempCoverImg()));
                 InputStream coverPageIps = this.getClass().getClassLoader().getResourceAsStream("titlepage.xhtml")
            ) {
                book.setCoverImage(new Resource(coverImageIps, "cover.jpeg"));
                book.setCoverPage(new Resource(coverPageIps, "titlepage.xhtml"));
            }
            context.setVariable("title", "内容简介");
            context.setVariable("contents", multiLevelBook.getIntros());
            book.addSection("内容简介", new Resource(engine.process("template", context).getBytes(StandardCharsets.UTF_8), "内容简介.html"));
            List<Volume> volumes = multiLevelBook.getVolumes();
            if (volumes.size() == 1) {
                Volume volume = volumes.get(0);
                List<Chapter> chapters = volume.getChapters();
                for (Chapter chapter : chapters) {
                    context.setVariable("title", chapter.getName());
                    context.setVariable("contents", chapter.getContent());
                    String out = engine.process("template", context);
                    Resource resource = new Resource(out.getBytes(StandardCharsets.UTF_8), chapter.getName().trim().replace("%", "") + ".html");
                    book.addSection(chapter.getName(), resource);
                }
            } else {
                TableOfContents tableOfContents = book.getTableOfContents();
                for (Volume volume : volumes) {
                    context.setVariable("title", volume.getName());
                    Resource resource = new Resource(engine.process("volume", context).getBytes(StandardCharsets.UTF_8), volume.getName() + ".html");
                    TOCReference root = new TOCReference(volume.getName(), resource);
                    tableOfContents.addTOCReference(root);
                    book.addResource(resource);
                    if (book.getSpine().findFirstResourceById(resource.getId()) < 0) {
                        book.getSpine().addSpineReference(new SpineReference(resource));
                    }
                    for (Chapter chapter : volume.getChapters()) {
                        try {
                            context.setVariable("title", chapter.getName());
                            context.setVariable("contents", chapter.getContent());
                            book.addSection(root, chapter.getName(), new Resource(engine.process("template", context).getBytes(StandardCharsets.UTF_8), chapter.getName().trim().replace("%", "") + ".html"));
                        } catch (NullPointerException ex) {
                            System.out.println(chapter);
                        }
                    }
                }
            }
            EpubWriter epubWriter = new EpubWriter();
            epubWriter.write(book, Files.newOutputStream(file.toPath()));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


    }

    public void showContent(MouseEvent mouseEvent) {
        TreeItem treeItem = (TreeItem) directoryTree.getSelectionModel().getSelectedItem();
        Chapter value = (Chapter) treeItem.getValue();
        List<String> content = value.getContent();
        String join = String.join(System.lineSeparator(), content);
        contentText.setText(join);
    }

    @FXML
    void initialize() {
        // 当introPane的宽度发生改变时，通过listener来更新bookIntrosText的自动换行宽度
        introPane.widthProperty().addListener((observable, oldValue, newValue) -> bookIntrosText.setWrappingWidth(newValue.doubleValue() - 10));
    }

    public void chooseImage(MouseEvent mouseEvent) throws IOException {
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("请选择小说封面");
        fileChooser.getExtensionFilters().addAll(
                new FileChooser.ExtensionFilter("图片", "*.*")
        );
        fileChooser.setInitialDirectory(new java.io.File("."));
        fileChooser.setInitialFileName("小说.txt");
        File file = fileChooser.showOpenDialog(chooseBtn.getScene().getWindow());
        if (file == null) {
            return;
        }
        String tempDir = PathUtil.getTempDir();
        // 获取临时目录
        String tempFile = tempDir + "cover.webp";
        BufferedImage image = ImageIO.read(file);
        ImageIO.write(image, "jpeg", new File(PathUtil.getTempCoverImg()));
        coverImage.setImage(new Image("file:" + PathUtil.getTempCoverImg()));
    }
}
